package com.ghy.ic.mo.controller;

import com.ghy.ic.mo.common.SendTextMsgCommon;
import com.ghy.ic.mo.dao.BcsDriverInfo;
import com.ghy.ic.mo.dao.BcsMessage;
import com.ghy.ic.mo.dao.BcsUserBookCarInfo;
import com.ghy.ic.mo.dao.BcsVehicleDeliveryInfo;
import com.ghy.ic.mo.domain.bo.BookUserInfoOfCsvBo;
import com.ghy.ic.mo.domain.bo.User;
import com.ghy.ic.mo.domain.vo.DriverInfoVo;
import com.ghy.ic.mo.domain.vo.OutResult;
import com.ghy.ic.mo.domain.vo.VehicleDeliveryInfoVo;
import com.ghy.ic.mo.utils.ExportUtil;
import com.ghy.ic.mo.utils.JodaTimeUtil;
import com.ghy.ic.mo.utils.ObjectUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.core.Controller;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.PathKit;
import com.jfinal.qyweixin.sdk.api.ApiConfigKit;
import com.jfinal.qyweixin.sdk.api.JsTicket;
import com.jfinal.qyweixin.sdk.api.JsTicketApi;
import org.apache.log4j.Logger;

import java.util.*;

import static com.ghy.ic.mo.constant.BcsConstant.*;

/**
 * @author Y-Tree
 * @date 18-12-1 下午10:52
 */
public class ManageController extends Controller {

    private static final Logger LOGGER =Logger.getLogger(ManageController.class);

    private static final String MANAGE_RESULT = "manageResult";
    private static final String UPDATE_FAIL = "更新失败！";
    private static final String UPDATE_SUCCESS = "更新成功！";
    private static final String GET_DRIVER_LIST_INFO_FAIL = "获取司机列表失败！";
    private static final String GET_DRIVER_LIST_INFO_SUCCESS = "获取司机列表成功！";
    private static final String GET_VEHICLE_DELIVERY_FAIL = "获取车辆派送信息失败！";
    private static final String GET_VEHICLE_DELIVERY_SUCCESS = "获取车辆派送信息成功！";
    private static final String CLOSE_SERVICE_FAIL = "该服务已结束，关闭服务失败！";
    private static final String CLOSE_SERVICE_SUCCESS = "关闭服务成功！";
    private static final String CLOSE_SERVICE_CAN_NOT_OPERATE_MULTIPLE_TIMES = "关闭服务不能多次操作！";
    private static final String OPEN_SERVICE_FAIL = "开启服务失败！";
    private static final String OPEN_SERVICE_SUCCESS = "开始服务成功！";
    private static final String SEND_MESSAGE_FAIL = "发送消息失败！";
    private static final String SEND_MESSAGE_SUCCESS = "发送消息成功！";
    private static final String GET_DRIVER_INFO_FAIL = "获取司机失败！";
    private static final String GET_DRIVER_INFO_SUCCESS = "获取司机成功！";
    private static final String CSV_FILE_DOWNLOAD_FAIL = "csv文件下载失败！";
    private static final String CSV_FILE_DOWNLOAD_SUCCESS = "csv文件下载成功！";

    private static final String PARA_MAX_NUM = "maxNum";
    private static final String PARA_ARRIVE_LOCATION = "arriveLocation";
    private static final String PARA_DEPARTURE_LOCATION = "departureLocation";
    private static final String PARA_TIME_MARK = "timeMark";
    private static final String PARA_DEPARTURE_DATE = "departureDate";
    private static final String PARA_DEPARTURE_TIME = "departureTime";
    private static final String PARA_DRIVER_NAME = "driverName";
    private static final String PARA_DRIVER_TELEPHONE = "driverTel";
    private static final String PARA_ID = "id";
    private static final String PARA_MESSAGE_BODY = "messageBody";
    private static final String PARA_VEHICLE_DELIVERY_ID = "vehicleDeliveryId";
    private static final String PARA_DRIVER_ID = "driverId";


    /**
     * 更新车辆派送信息
     */
    public void update(){

        // 1. 获取用户提交信息
        int maxNUm = getParaToInt(PARA_MAX_NUM);
        String arriveLocation = getPara(PARA_ARRIVE_LOCATION);
        String departureLocation = getPara(PARA_DEPARTURE_LOCATION);
        Integer timeMark = getParaToInt(PARA_TIME_MARK);
        String departureDate = getPara(PARA_DEPARTURE_DATE);
        String departureTime = getPara(PARA_DEPARTURE_TIME);
        String driverName = getPara(PARA_DRIVER_NAME);
        String driverTelephone = getPara(PARA_DRIVER_TELEPHONE);

        // 1.1 对比司机信息，不同就对司机信息进行修改
        String[] driverList = driverName.split(",");
        ArrayList<Integer> driverIds = Lists.newArrayList();
        for (int i = 0; i < driverList.length; i++){

            BcsDriverInfo driverInfo = BcsDriverInfo.getDriverInfoById(BcsDriverInfo.getIdByDriverName(driverList[i]));
            String driverTelOld = driverInfo.getDriverTelephone();
            String driverTelNew = driverTelephone.split(",")[i];
            Integer driverId = driverInfo.getId();
            driverIds.add(driverId);
            if (!driverTelOld.equals(driverTelNew)){
                // 不同，对司机信息进行更新
                BcsDriverInfo.update(driverId, driverList[i], driverTelNew);
            }

        }

        // 2. 将信息存入数据库
        String driverIdStr = org.apache.commons.lang3.StringUtils.join(driverIds, ",");
        int id = getParaToInt(PARA_ID);

        BcsVehicleDeliveryInfo bcsVehicleDeliveryInfo = new BcsVehicleDeliveryInfo();
        bcsVehicleDeliveryInfo.setArriveLocation(arriveLocation);
        bcsVehicleDeliveryInfo.setMaxNum(maxNUm);
        bcsVehicleDeliveryInfo.setDepartureLocation(departureLocation);
        bcsVehicleDeliveryInfo.setDepartureDate(departureDate);
        bcsVehicleDeliveryInfo.setDepartureTime(departureTime);
        bcsVehicleDeliveryInfo.setTimeMark(timeMark);
        bcsVehicleDeliveryInfo.setDriverId(driverIdStr);

        if (!BcsVehicleDeliveryInfo.updateAll(bcsVehicleDeliveryInfo, id)){

            returnResultFail(UPDATE_FAIL);
        }else {

            returnResultSuccess(UPDATE_SUCCESS, UPDATE_SUCCESS);
        }
    }

    /**
     * 关闭车辆派送服务接口的更新，添加关闭服务后给已预约的用户发送“服务关闭消息”，
     * 并返回操作者的基本信息给用户，方便联系
     */
    public void closeService(){

        int vDId = getParaToInt(PARA_VEHICLE_DELIVERY_ID);
        String sendMessage = "";

        // 1. 停止服务前，首先判断该服务当前状态，只有进行中的服务才能进行进行停止
        BcsVehicleDeliveryInfo vehicleDeliveryInfo = BcsVehicleDeliveryInfo.getInfoById(vDId);
        Integer serviceStatus = vehicleDeliveryInfo.getServiceStatus();

        // 拼接给用户发送的消息体
        String departureDate = vehicleDeliveryInfo.getDepartureDate();
        String departureTime = vehicleDeliveryInfo.getDepartureTime();
        sendMessage = "管理员关闭了“" + departureDate + " " + departureTime + "”的服务！";

        if (serviceStatus == END){

            // 表明服务已结束，不能对该次服务更改
            returnResultFail(CLOSE_SERVICE_FAIL);
        }else if(serviceStatus == STOP){
            // 表明服务已经被取消过
            returnResultFail(CLOSE_SERVICE_CAN_NOT_OPERATE_MULTIPLE_TIMES);
        }else {

            // 表明服务还在“进行中”，可以进行关闭服务操作， 并在操作成功后给用户发送取消通知消息
            if (BcsVehicleDeliveryInfo.updateByServiceFlag(vDId, CANCEL_SERVICE)){
                // 1. 根据vDId获取用户列表
                List<BcsUserBookCarInfo> bookUserList
                        = BcsUserBookCarInfo.getBcsUserBookCarInfosByVehicleDeliveryId(vDId);
                LOGGER.info("bookUserList size : " + bookUserList.size());
                // 2. 给预约的每位用户发送消息
                for(BcsUserBookCarInfo bookUser : bookUserList){

                    String userId = bookUser.getUserId();
                    LOGGER.info("存在预约用户 ： " + userId);
                    SendTextMsgCommon.sendTextMsg(userId, sendMessage);
                }
                returnResultSuccess(CLOSE_SERVICE_SUCCESS, CLOSE_SERVICE_SUCCESS);
            }else {
                returnResultFail(CLOSE_SERVICE_FAIL);
            }
        }
    }

    /**
     * 开启车辆派送服务
     */
    public void openService(){

        int vDId = getParaToInt(PARA_VEHICLE_DELIVERY_ID);
        int serviceFlag = 0;

        // 1. 停止服务前，首先判断该服务当前状态，只有进行中的服务才能进行进行停止
        Integer serviceStatus = BcsVehicleDeliveryInfo.getInfoById(vDId).getServiceStatus();
        if (serviceStatus == END){

            // 表明服务已结束，不能对该次服务更改
            returnResultFail(OPEN_SERVICE_FAIL);
        }else {
            if (!BcsVehicleDeliveryInfo.updateByServiceFlag(vDId, serviceFlag)){

                returnResultFail(OPEN_SERVICE_FAIL);
            }else {

                returnResultSuccess(OPEN_SERVICE_SUCCESS, OPEN_SERVICE_SUCCESS);
            }
        }

    }

    /**
     * 获取车辆派送信息
     */
    public void getBaseInfoByDepartureDateAndTimeMark(){

        int timeMark = getParaToInt(PARA_TIME_MARK);
        String departureDate = getPara(PARA_DEPARTURE_DATE);

        BcsVehicleDeliveryInfo info
                = BcsVehicleDeliveryInfo.getInfoByDepartureDateAndTimeMark(departureDate, timeMark);
        getBaseInfoUtil(info);
    }

    /**
     * 根据vehicleDeliveryId获取车辆派送id
     */
    public void getBaseInfoByVehicleDeliveryId(){
        int vDId = getParaToInt(PARA_VEHICLE_DELIVERY_ID);

        BcsVehicleDeliveryInfo info = BcsVehicleDeliveryInfo.getInfoById(vDId);
        getBaseInfoUtil(info);
    }

    /**
     * 获取司机列表
     */
    public void getDriverList(){

        List<BcsDriverInfo> driverInfoList = BcsDriverInfo.getDriverInfoList();

        if (driverInfoList.isEmpty()){

            returnResultFail(GET_DRIVER_LIST_INFO_FAIL);
        }else {

            returnResultSuccess(GET_DRIVER_LIST_INFO_SUCCESS, driverInfoList);
        }
    }

    /**
     * 根据司机编号获取司机信息
     */
    public void getDriverInfo(){

        int driverId = getParaToInt(PARA_DRIVER_ID);
        BcsDriverInfo info = BcsDriverInfo.getDriverInfoById(driverId);

        if (info == null){
            returnResultFail(GET_DRIVER_INFO_FAIL);
        }else {
            returnResultSuccess(GET_DRIVER_INFO_SUCCESS, info);
        }
    }

    /**
     * 给已经预约的用户发送通知
     */
    public void sendMessage(){

        int vDId = getParaToInt(PARA_VEHICLE_DELIVERY_ID);
        String messageBody = getPara(PARA_MESSAGE_BODY);

        // 1. 将发送消息记录存入数据库
        String userName;
        User user = getSessionAttr("user");
        if (user != null){
            userName = user.getName();
        }else {
            userName = "胡腾云";
        }

        BcsMessage bcsMessage = new BcsMessage();
        bcsMessage.setVehicleDeliveryId(vDId);
        bcsMessage.setSender(userName);
        bcsMessage.setMessageBody(messageBody);

        if (BcsMessage.add(bcsMessage)){
            // 2. 获取已经预约的用户。
            List<BcsUserBookCarInfo> bookUsers = BcsUserBookCarInfo.getBcsUserBookCarInfosByVehicleDeliveryId(vDId);

            // 无预约用户
            if (bookUsers.isEmpty()){

                LOGGER.info("无预约用户");
                returnResultFail(SEND_MESSAGE_FAIL);
                return;
            }

            LOGGER.info("存在预约用户");
            // 有预约用户存在
            if (user != null){
                for (BcsUserBookCarInfo bookUser : bookUsers){

                    // 3. 给每个用户发送消息。 生产环境
                    String userId = bookUser.getUserId();
                    LOGGER.info("存在预约用户 ： " + userId);
                    SendTextMsgCommon.sendTextMsg(userId, messageBody);
                }
            }else {
                // 用户测试环境
                LOGGER.info("预约用户存在 ： " + bookUsers.size());
            }

            returnResultSuccess(SEND_MESSAGE_SUCCESS, SEND_MESSAGE_SUCCESS);
        }else {
            returnResultFail(SEND_MESSAGE_FAIL);
        }

    }

    /**
     * 导出数据, 返回url路径
     */
    public void exportData(){

        int vDId = getParaToInt(PARA_VEHICLE_DELIVERY_ID);
        List<BcsUserBookCarInfo> bookCarInfoList
                = BcsUserBookCarInfo.getBcsUserBookCarInfosByVehicleDeliveryId(vDId);
        BcsVehicleDeliveryInfo vehicleDeliveryInfo = BcsVehicleDeliveryInfo.getInfoById(vDId);
        String outFileName = vehicleDeliveryInfo.getDepartureDate() + "_" + vehicleDeliveryInfo.getDepartureTime().replace(":", "-") + ".csv";
        String outPutPath = PathKit.getWebRootPath() + "/download/" + outFileName;

        // http://localhost:8099/manage/exportData
        LOGGER.info("Scheme : " + getRequest().getScheme());
        LOGGER.info("ServerPort : " + getRequest().getServerPort());
        LOGGER.info("ServerName : " + getRequest().getServerName());

        String csvFileDownloadUrl = getRequest().getScheme() + "://" + getRequest().getServerName() + ":" + getRequest().getServerPort()
                + "/bcs/download/" + outFileName;
        LOGGER.info(csvFileDownloadUrl);

        List<Map<String, Object>> dataList = Lists.newArrayList();
        List<BookUserInfoOfCsvBo> bookUserInfoOfCsvList = Lists.newArrayList();

        int number = 0;
        for (BcsUserBookCarInfo bookCarInfo : bookCarInfoList){

            number++;
            BookUserInfoOfCsvBo userInfoOfCsvBo = new BookUserInfoOfCsvBo();
            userInfoOfCsvBo.setId(number);
            userInfoOfCsvBo.setSubmitterName(bookCarInfo.getUserName());
            userInfoOfCsvBo.setSubmitterTelephone(bookCarInfo.getUserTelephone());
            if (bookCarInfo.getAgent() == null){

                userInfoOfCsvBo.setAgentName("空");
            }else {
                userInfoOfCsvBo.setAgentName(bookCarInfo.getAgent());
            }

            userInfoOfCsvBo.setDepartureDate(vehicleDeliveryInfo.getDepartureDate());
            userInfoOfCsvBo.setDepartureTime(vehicleDeliveryInfo.getDepartureTime());
            userInfoOfCsvBo.setCreateTime(JodaTimeUtil.date2String(bookCarInfo.getCreateTime()));
            bookUserInfoOfCsvList.add(userInfoOfCsvBo);
        }

        for (BookUserInfoOfCsvBo bookUserInfoOfCsv : bookUserInfoOfCsvList){

            try {
                LOGGER.info(bookUserInfoOfCsv.toString());
                dataList.add(ObjectUtil.objectToMap(bookUserInfoOfCsv));
            } catch (IllegalAccessException e) {
                LOGGER.error("出异常了 ： " + e);
            }
        }

        boolean createCsvFileFlag = ExportUtil.createCsvFile(dataList, COL_NAME, MAP_KEY, outPutPath);
        if (createCsvFileFlag){
            returnResultSuccess(CSV_FILE_DOWNLOAD_SUCCESS, csvFileDownloadUrl);
        }else {
            returnResultFail(CSV_FILE_DOWNLOAD_FAIL);
        }
    }

    /**
     * 获取服务器时间
     */
    public void getServiceCurrentDateTime(){

        setAttr(MANAGE_RESULT, new OutResult().resultMap(0, "ok", JodaTimeUtil.getCurrentDateTimeOfTimestamp()));
        renderJson(MANAGE_RESULT, new OutResult().resultMap(0, "ok", JodaTimeUtil.getCurrentDateTimeOfTimestamp()));
    }

    public void jsSdkJson(){

        String url = getPara("url");
        LOGGER.info("url>>>>" + url);

        JsTicket jsApiTicket = JsTicketApi.getTicket(JsTicketApi.JsApiType.jsapi);
        String jsapiTicket = jsApiTicket.getTicket();
        String nonceStr = createNonceStr();
        String timestamp = createTimestamp();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        //注意这里参数名必须全部小写，且必须有序
        String  str = "jsapi_ticket=" + jsapiTicket +
                "&noncestr=" + nonceStr +
                "&timestamp=" + timestamp +
                "&url=" + url;
        String signature = HashKit.sha1(str);

        LOGGER.info("appId " + ApiConfigKit.getApiConfig().getCorpId()
                + "  nonceStr " + nonceStr + " timestamp " + timestamp);
        LOGGER.info("url " + url + " signature " + signature);
        LOGGER.info("nonceStr " + nonceStr + " timestamp " + timestamp);
        LOGGER.info("jsapi_ticket " + jsapiTicket);
        LOGGER.info("nonce_str  " + nonceStr);
        HashMap<String, Object> map = Maps.newHashMap();
        map.put("appId", ApiConfigKit.getApiConfig().getCorpId());
        map.put("nonceStr", nonceStr);
        map.put("timestamp", timestamp);
        map.put("url", url);
        map.put("signature", signature);
        map.put("jsApiTicket", jsapiTicket);
        setAttr("jsSdkResult",new OutResult().resultMap(0, "ok", map));
        renderJson("jsSdkResult",new OutResult().resultMap(0, "ok", map));
    }

    /**
     * @param failMes 消息体
     */
    private void returnResultFail(String failMes){

        LOGGER.error(failMes);
        setAttr(MANAGE_RESULT, new OutResult().resultMap(1, "err", failMes));
        renderJson(MANAGE_RESULT, new OutResult().resultMap(1, "err", failMes));
    }

    /**
     * @param successMes 消息体
     * @param data 返回数据
     */
    private void returnResultSuccess(String successMes, Object data){

        LOGGER.info(successMes);
        setAttr(MANAGE_RESULT, new OutResult().resultMap(0, "ok", data));
        renderJson(MANAGE_RESULT, new OutResult().resultMap(0, "ok", data));
    }

    private void getBaseInfoUtil(BcsVehicleDeliveryInfo info){

        if (info == null){
            returnResultFail(GET_VEHICLE_DELIVERY_FAIL);
        }else {
            // 封装车辆派送信息
            VehicleDeliveryInfoVo infoVo = new VehicleDeliveryInfoVo();

            infoVo.setVehicleDeliveryId(info.getId());
            infoVo.setArriveLocation(info.getArriveLocation());
            infoVo.setDepartureLocation(info.getDepartureLocation());
            infoVo.setBookNum(info.getBookNum());
            infoVo.setMaxNum(info.getMaxNum());
            infoVo.setDepartureDate(info.getDepartureDate());
            infoVo.setDepartureTime(info.getDepartureTime());
            infoVo.setServiceFlag(info.getServiceFlag());
            infoVo.setServiceStatus(info.getServiceStatus());
            infoVo.setTimeMark(info.getTimeMark());

            // 封装司机信息
            ArrayList<DriverInfoVo> driverInfoVoList =  Lists.newArrayList();
            if (info.getDriverId() != null){
                String[] driverIds = info.getDriverId().split(",");
                for (String driverIdStr : driverIds){

                    int driverId = Integer.parseInt(driverIdStr);
                    DriverInfoVo driverInfoVo = new DriverInfoVo();
                    BcsDriverInfo driverInfo = BcsDriverInfo.getDriverInfoById(driverId);
                    driverInfoVo.setId(driverId);
                    driverInfoVo.setDriverName(driverInfo.getDriverName());
                    driverInfoVo.setDriverTelephone(driverInfo.getDriverTelephone());
                    driverInfoVo.setDriverImg(driverInfo.getDriverImg());
                    driverInfoVoList.add(driverInfoVo);
                }

                infoVo.setDriverInfoVoList(driverInfoVoList);
            }


            returnResultSuccess(GET_VEHICLE_DELIVERY_SUCCESS, infoVo);
        }
    }

    private static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    private static String createNonceStr() {
        return UUID.randomUUID().toString();
    }
}
